#include "llcc68_hal.h"

llcc68_hal_status_t llcc68_hal_write( const void* context, const uint8_t* command, const uint16_t command_length, const uint8_t* data, const uint16_t data_length )
{
	//taskENTER_CRITICAL();
	uint16_t write_len = command_length + data_length;
	uint8_t *write_buf = pvPortCalloc(write_len, sizeof(uint8_t));
	uint8_t recv_buf;
	
	SPI1_CS_LOW();
	memcpy(write_buf, command, command_length);
	memcpy(write_buf + command_length, data, data_length);
	
	// RX
	DMA1_CHANNEL1->dtcnt = (uint32_t)write_len;
	DMA1_CHANNEL1->maddr = (uint32_t)&recv_buf;
	DMA1_CHANNEL1->ctrl_bit.mincm = FALSE;
	// TX
	DMA1_CHANNEL2->dtcnt = (uint32_t)write_len;
	DMA1_CHANNEL2->maddr = (uint32_t)write_buf;
	
	dma_channel_enable(DMA1_CHANNEL1, TRUE);
	dma_channel_enable(DMA1_CHANNEL2, TRUE);
  while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
	dma_flag_clear(DMA1_FDT1_FLAG);
	dma_channel_enable(DMA1_CHANNEL1, FALSE);
	dma_channel_enable(DMA1_CHANNEL2, FALSE);
	
	while(spi_i2s_flag_get(SPI1, SPI_I2S_BF_FLAG) != RESET);
	SPI1_CS_HIGH();
	vTaskDelay(pdMS_TO_TICKS(1));
	while(LLCC68_BUSY_READ() != RESET);
	vPortFree(write_buf);
	//taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_OK;
}

llcc68_hal_status_t llcc68_hal_read( const void* context, const uint8_t* command, const uint16_t command_length, uint8_t* data, const uint16_t data_length )
{
	//taskENTER_CRITICAL();
	
	uint16_t write_len = command_length + data_length;
	uint8_t *write_buf = pvPortCalloc(write_len, sizeof(uint8_t));
	uint8_t *recv_buf = pvPortCalloc(write_len, sizeof(uint8_t));
	
	memcpy(write_buf, command, command_length);

	SPI1_CS_LOW();
	// RX
	DMA1_CHANNEL1->dtcnt = (uint32_t)write_len;
	DMA1_CHANNEL1->maddr = (uint32_t)recv_buf;
	DMA1_CHANNEL1->ctrl_bit.mincm = TRUE;
	// TX
	DMA1_CHANNEL2->dtcnt = (uint32_t)write_len;
	DMA1_CHANNEL2->maddr = (uint32_t)write_buf;
	dma_channel_enable(DMA1_CHANNEL1, TRUE);
	dma_channel_enable(DMA1_CHANNEL2, TRUE);
	// wait flag
	while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
	dma_flag_clear(DMA1_FDT1_FLAG);
	dma_channel_enable(DMA1_CHANNEL1, FALSE);
	dma_channel_enable(DMA1_CHANNEL2, FALSE);
	
	while(spi_i2s_flag_get(SPI1, SPI_I2S_BF_FLAG) != RESET);
	SPI1_CS_HIGH();
	vTaskDelay(pdMS_TO_TICKS(1));
	while(LLCC68_BUSY_READ() != RESET);
	memcpy(data, recv_buf + command_length, data_length);
	vPortFree(write_buf);
	vPortFree(recv_buf);
	
	//taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_OK;
}

llcc68_hal_status_t llcc68_hal_reset( const void* context )
{
	taskENTER_CRITICAL();
	LLCC68_RST_HIGH();
	LLCC68_RST_LOW();
	//delay_ms(1);
	vTaskDelay(pdMS_TO_TICKS(1));
	LLCC68_RST_HIGH();
	vTaskDelay(pdMS_TO_TICKS(1));
	while(LLCC68_BUSY_READ() != RESET);
	taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_OK;
}

llcc68_hal_status_t llcc68_hal_wakeup( const void* context )
{
	taskENTER_CRITICAL();
	SPI1_CS_LOW();
	//delay_us(200);
	vTaskDelay(pdMS_TO_TICKS(1));
	SPI1_CS_HIGH();
	taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_ERROR;
}